﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

using ColladaDotNet;
using ColladaDotNet.OpenTKMapping;

using Microsoft.Xml.Serialization.GeneratedAssembly;

namespace MergeDae
{
	class Program
	{
		static void Main(string[] args)
		{
#if DEBUG
			if (args.Length == 0)
			{
				args =
						@"-s src\man_pistol.DAE -d src\torso.DAE -o mix\man_torso_pistol.DAE library_animations library_cameras #node-Dummy01 #node-Bip01 #node-Pistol"
								.Split(
								new char[] {' '});
			}
#else
#endif
			string srcFileName = null;
			string dstFileName = null;
			string outputFileName = null;

			COLLADA.Serializer = new COLLADASerializer();

			List<string> nodes = new List<string>();

			for (int i = 0; i < args.Length; i++)
			{
				var arg = args[i];
				if (arg[0] == '-' || arg[0] == '/')
				{
					switch (arg.Substring(1).ToLower())
					{
						case "s":
						case "source":
						case "i":
						case "input":
							srcFileName = args[i + 1];
							++i;
							break;
						case "d":
						case "destination":
							dstFileName = args[i + 1];
							++i;
							break;
						case "o":
						case "output":
							outputFileName = args[i + 1];
							++i;
							break;
					}
				}
				else
				{
					nodes.Add(arg);
				}
			}


			COLLADA src = COLLADA.Load(srcFileName);
			COLLADA dst = COLLADA.Load(dstFileName);

			foreach (var s in nodes)
			{
				var n = src.GetElementByUrl(s);
				if (n == null)
				{
					throw new ApplicationException(s+" not found");
				}
				if ((n.GetType() == typeof(library_animations)) || (n.GetType() == typeof(library_cameras)) || (n.GetType() == typeof(library_materials)))
				{
					dst.Items = ReplaceByType(dst.Items, n);
				}
				else if (n.GetType() == typeof(node))
				{
					visual_scene scene = null;
					if (dst.scene == null)
					{
						var lib = dst.library_visual_scenes;
						if (lib != null)
						{
							if (lib.visual_scene != null && lib.visual_scene.Length > 0)
								scene = (visual_scene)lib.visual_scene[0];
						}
					}
					else
					{
						scene = (visual_scene)dst.GetElementByUrl(dst.scene.instance_visual_scene.url);
					}
					var nodeToReplace = dst.GetElementByUrl(s) as node;
					if (nodeToReplace != null)
					{
						nodeToReplace.asset = ((node)n).asset;
						nodeToReplace.node1 = ((node)n).node1;
						nodeToReplace.instance_camera = ((node)n).instance_camera;
						nodeToReplace.instance_geometry = ((node)n).instance_geometry;
						nodeToReplace.instance_controller = ((node)n).instance_controller;
						nodeToReplace.instance_node = ((node)n).instance_node;
						nodeToReplace.instance_light = ((node)n).instance_light;
						nodeToReplace.Items = ((node)n).Items;
						nodeToReplace.ItemsElementName = ((node)n).ItemsElementName;
						nodeToReplace.layer = ((node)n).layer;
						nodeToReplace.extra = ((node)n).extra;
						nodeToReplace.sid = ((node)n).sid;
					}
					else
					{
						var dstnodes = new node[scene.node.Length + 1];
						scene.node.CopyTo(dstnodes, 0);
						dstnodes[scene.node.Length] = (node)n;
						scene.node = dstnodes;
					}
				}
				else 
					throw new ApplicationException(n.GetType().FullName + " is not supported");
			}

			if (string.IsNullOrEmpty(outputFileName))
				outputFileName = dstFileName;
			if (File.Exists(outputFileName))
				File.Copy(outputFileName, outputFileName + ".bak",true);
			dst.Save(outputFileName);
		}

		private static ColladaXmlNode[] ReplaceByType(ColladaXmlNode[] items, ColladaXmlNode n)
		{
			ColladaXmlNode[] res;
			for (int i = 0; i < items.Length; i++)
			{
				var item = items[i];
				if (item.GetType() == n.GetType())
				{
					res = new ColladaXmlNode[items.Length];
					items.CopyTo(res, 0);
					res[i] = n;
					return res;
				}
			}
			res = new ColladaXmlNode[items.Length+1];
			items.CopyTo(res, 0);
			res[items.Length] = n;
			return res;
		}
	}
}
